package app

import (
	"context"
	"fmt"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/golang-jwt/jwt/v5"
	"github.com/samber/lo"
)

var jwt密钥 []byte

func C初始化令牌() {
	配置值, 错误 := g.Cfg().Get(context.TODO(), "jwt.secret")
	if 错误 != nil {
		g.Log().Fatal(context.TODO(), 错误)
	}
	jwt密钥 = 配置值.Bytes()
	if len(jwt密钥) < 16 {
		g.Log().Fatal(context.TODO(), "jwt.secret不能小于16位")
	}
}

func R认证中间件(请求 *ghttp.Request) {
	认证头 := 请求.Request.Header.Get("Authorization")

	if 认证头 != "" {
		上下文 := 请求.Context()
		令牌, 错误 := jwt.Parse(认证头, func(令牌 *jwt.Token) (interface{}, error) {
			if _, 有效 := 令牌.Method.(*jwt.SigningMethodHMAC); !有效 {
				return nil, fmt.Errorf("非预期的签名方法: %v", 令牌.Header["alg"])
			}

			return jwt密钥, nil
		})

		if 错误 != nil {
			g.Log().Info(上下文, "令牌错误", 错误)
			请求.Response.WriteJson(g.Map{
				"code": 401,
				"msg":  "未知错误",
			})
			return
		}

		用户ID := ""
		if 声明, 有效 := 令牌.Claims.(jwt.MapClaims); 有效 && 令牌.Valid {
			用户ID = gconv.String(声明["userId"])
			if 用户ID == "" {
				g.Log().Info(上下文, "用户ID为空")
				请求.Response.WriteJson(g.Map{
					"code": 401,
					"msg":  "用户登陆信息不存在",
				})
				return
			}
		} else {
			g.Log().Info(上下文, "令牌无效")
			请求.Response.WriteJson(g.Map{
				"code": 401,
				"msg":  "未知错误",
			})
			return
		}
		上下文 = context.WithValue(上下文, 用户ID键, &当前用户{用户ID: 用户ID})
		请求.SetCtx(上下文)
	} else {
		忽略路径 := []string{
			"/api/register",
			"/api/auth",
			"/api/icon",
		}

		if !lo.Contains(忽略路径, 请求.Request.URL.Path) {
			请求.Response.WriteJson(g.Map{
				"code": 401,
				"msg":  "未登录",
			})
			return
		}
	}

	请求.Middleware.Next()
}

func K跨域中间件(请求 *ghttp.Request) {
	跨域选项 := 请求.Response.DefaultCORSOptions()
	跨域选项.AllowOrigin = 请求.Request.Header.Get("Origin")
	请求.Response.CORS(跨域选项)
	请求.Middleware.Next()
}

func X响应中间件(请求 *ghttp.Request) {
	请求.Middleware.Next()

	响应数据 := 请求.GetHandlerResponse()
	错误 := 请求.GetError()
	if 错误 != nil {
		if 框架错误, 有效 := 错误.(*gerror.Error); 有效 {
			if 框架错误.Code() == gcode.CodeNil {
				请求.Response.WriteJson(g.Map{
					"code": 400,
					"msg":  错误.Error(),
				})

				请求.SetError(nil)
				return
			}
		}

		请求.Response.WriteJson(g.Map{
			"code": 500,
			"msg":  错误.Error(),
		})

		g.Log().Error(请求.Context(), 错误)
		return
	}

	if 响应数据 != nil {
		请求.Response.WriteJson(g.Map{
			"code": 200,
			"data": 响应数据,
			"msg":  "成功",
		})
	}
}
